#pragma once

#include "LDPC_Matrix.h"

void Check_LDPC_Encode();


/*
* 5G NR LDPC Encode
* matrix - The Check Matrix for LDPC
* Msg - Info Bits
* Code - LDPC Code with the Rate
* Code_Complete - The Complete LDPC Code
*/
bool LDPC_Encode(const LDPC_Matrix& matrix, const uint8_t* Msg, uint8_t* Code, uint8_t* Code_Complete);



/*
* LDPC Decode with Belief Propagation Algorithm
* STEP 1: $\Delta q_{mn} = q^0_{mn} - q^1_{mn}$
*		  $\Delta r_{mn} = \prod_{n' \in N(m)\backslash n} \Delta q_{mn'}$
*         $r^x_{mn} = (1+\Delta r_{mn})/2$
* STEP 2: $q^x_{mn} = \alpha_{mn}c^x_n\prod_{m'\in M(n)\backslash m}r^x_{m'n}$
*         $\alpha_{mn}=C\\  s.t. q^0_{mn}+q^1_{mn}=1$
* STEP 3: Repeat STEP 1 & 2 until MaxITR or Check Successfully.
*/
bool LDPC_Decode_BP(const LDPC_Matrix& matrix, const double sigma, const uint32_t MaxItr,
	const bool isExitBeforeMaxItr, const double* Signal, uint8_t* Decode, uint32_t& ITR);



/*
* LDPC Decode with Layered Belief Propagation Algorithm
*/
bool LDPC_Decode_LayeredBP(const LDPC_Matrix& matrix, const double sigma, const uint32_t MaxItr,
	const bool isExitBeforeMaxItr, const double* Signal, uint8_t* Decode, uint32_t& ITR);



/*
* Simulation For Decode Performance of 5G NR LDPC
* Belief Propagation Algorithm
*/
bool Simulation_BP(const LDPC_Matrix& matrix, const uint64_t Seed, const float EbN0,
	const uint64_t MinError, const uint64_t MaxTrans, const uint32_t MaxITR,
	const bool isExitBeforeMaxItr, const bool isPrintInfo,
	uint64_t& ErrorBits, uint64_t& TransBits, uint64_t& ErrorFrames, uint64_t& TransFrames,
	float& AveITR, float& AveTime, uint32_t Debug);


/*
* Simulation For Decode Performance of 5G NR LDPC
* Layered Belief Propagation Algorithm
*/
bool Simulation_LayeredBP(const LDPC_Matrix& matrix, const uint64_t Seed, const float EbN0,
	const uint64_t MinError, const uint64_t MaxTrans, const uint32_t MaxITR,
	const bool isExitBeforeMaxItr, const bool isPrintInfo,
	uint64_t& ErrorBits, uint64_t& TransBits, uint64_t& ErrorFrames, uint64_t& TransFrames,
	float& AveITR, float& AveTime, uint32_t Debug);